
#include "RtBase.h"
#include "RtTrace.h"

#ifdef RT_WIN32
#include <direct.h>
#include <shlobj.h>
#endif // RT_WIN32

#if !defined (RT_WIN32)
#	include <regex.h>
#	include <sys/time.h>
#else //!defined (WIN32)
#	include <time.h>
#endif //!defined (RT_WIN32)


void init_config(const char* cur_env);
unsigned char get_string_param(char* group, char* item_key, char* item_value, unsigned long len);
int get_int_param(char* group, char* item_key);
unsigned short get_uint16_param(char* group, char* item_key);
DWORD get_uint32_param(char* group, char* item_key);
unsigned char get_bool_param(char* group, char* item_key, unsigned char default_value);
void set_iwlab_home_env(char* home_env);
char* get_iwlab_home_env();
const char* get_process_name();
const char* get_exec_name(void);


/////////////////////////////////////////////////////////////////////////////
// File based get_int_from_profile() and get_string_from_profile()
// implementation
//
char* trim_string(char* str)
{
	RT_ASSERTE(str);
	
	// trim tail
	char* cur_str = str + strlen(str) - 1;
	while(cur_str >= str)
	{
		if(strchr(" \t\r\n", *cur_str))
		{
			*cur_str = 0;
			cur_str--;
		}
		else
		{
			break;
		}
	}
	
	// trim head
	cur_str = str;
	while(*cur_str)
	{
		if(strchr(" \t\r\n", *cur_str))
			cur_str++;
		else
			break;
	}
	return cur_str;
}

unsigned char is_comment_line(char* cur_str)
{
	while(*cur_str)
	{
		if(strchr(" \t\r\n", *cur_str) != NULL)
			cur_str++;
		else
			return *cur_str == '#';
	}
	return FALSE;
}

unsigned char read_init_file(FILE* f, char* app_name, char* key_name,
					   char* ret_str, unsigned long len)
{
	char buf[2048];
	unsigned char find_section = FALSE;
	
	while(!feof(f))
	{
		buf[0] = 0;
		if(!fgets(buf, sizeof(buf), f))
			break;
		
		if(is_comment_line(buf))
			continue;
		
		if(strchr(buf, '[') && strchr(buf, ']'))
		{
			if(find_section)
			{
				// encounter another section
				return FALSE;
			}
			else
			{
				char* token = strchr(buf, '[');
				token++;
				*strchr(buf, ']') = 0;
				
				token = trim_string(token);
#ifndef RT_WIN32
				if(strcasecmp(token, app_name) == 0)
					find_section = TRUE;
#else //RT_WIN32
				if(stricmp(token, app_name) == 0)
					find_section = TRUE;
				
#endif //RT_WIN32
			}
		}
		else
		{
			if(find_section)
			{
				char* token = strchr(buf, '=');
				if(token)
				{
					*token = 0;
					token++;
					
					char* pKey = trim_string(buf);
#ifndef RT_WIN32
					if(strcasecmp(pKey, key_name) == 0)
#else //RT_WIN32
						if(stricmp(pKey, key_name) == 0)
#endif //RT_WIN32
						{
							token = trim_string(token);
							if(*token == '\'' || *token == '"')
							{
								int str_len = strlen(token);
								if(token[str_len-1] == *token)
								{
									token[str_len-1] = 0;
									token++;
									token = trim_string(token);
								}
							}
							strncpy(ret_str, token, len);
							return TRUE;
						}
				}
			}
		}
	}
	return FALSE;
}

int get_int_from_profile(char* app_name, char* key_name,
						 int default_value, char* file_name)
{
	int i;
	
	FILE* f = fopen(file_name, "rt");
	if(!f)
		return default_value;
	
	//    SET_CLOSEONEXEC(fileno(f));
	
	char buf[256];
	if(read_init_file(f, app_name, key_name, buf, 256))
	{
		fclose(f);
		sscanf(buf, "%d", &i);
		return i;
	}
	fclose(f);
	
	return default_value;
}

unsigned long get_string_from_profile(char* app_name, char* key_name,
							   char* default_str, char* ret_str, unsigned long len, char* file_name)
{
	FILE* f = fopen(file_name, "rt");
	if(!f)
	{
		strncpy(ret_str, default_str, len - 1);
		return strlen(ret_str);
	}
	
	//    SET_CLOSEONEXEC(fileno(f));
	
	if(read_init_file(f, app_name, key_name, ret_str, len))
	{
		fclose(f);
		return strlen(ret_str);
	}
	fclose(f);
	
	strncpy(ret_str, default_str, len - 1);
	return strlen(ret_str);
}

char g_cur_env[512] = "IWLAB_RT_HOME";
const int G_DEF_IWLAB_HOME_DIR_MAX = 512;
#if !defined(RT_WIN32)
char g_def_iwlab_home_dir[G_DEF_IWLAB_HOME_DIR_MAX] = "/tmp/";
#else
char g_def_iwlab_home_dir[G_DEF_IWLAB_HOME_DIR_MAX] = ".";
#endif //!defined(RT_WIN32)


void set_iwlab_home_env(char* home_env)
{
	strncpy(g_cur_env, home_env, sizeof(g_cur_env));
}

char* get_iwlab_home_env()
{
	char* p = 0;
#if !defined(RT_WIN32)
	 //p = getenv(g_cur_env);
	 p = getcwd(g_def_iwlab_home_dir,G_DEF_IWLAB_HOME_DIR_MAX);
#else// !defined(RT_WIN32)
		GetCurrentDirectory(G_DEF_IWLAB_HOME_DIR_MAX,g_def_iwlab_home_dir);
#endif //!defined(RT_WIN32)
	if (!p)
		p = g_def_iwlab_home_dir;
	
	return p;
}

char* get_iwlab_home_dir()
{
	return get_iwlab_home_env();
}

void get_config_file_name(char* file_name)
{
	char* iwlab_home_dir = get_iwlab_home_env();
	if(iwlab_home_dir)
	{
#if !defined(RT_WIN32)
		strcpy(file_name, iwlab_home_dir);
		if(file_name[strlen(file_name) - 1] != '/')
			strcat(file_name, "/");
		strcat(file_name, "conf/skycfg.ini");
#else //!defined(RT_WIN32)
		strcpy(file_name, iwlab_home_dir);
		if(file_name[strlen(file_name) - 1] != '\\')
			strcat(file_name, "\\");
		strcat(file_name, "conf\\skycfg.ini");
#endif // !defined(RT_WIN32)
	}
	else
	{
		strcpy(file_name, "/tmp/skycfg.ini");
	}
}

void init_config(const char* cur_env)
{
	if(cur_env && strlen(cur_env) < sizeof(g_cur_env) - 1)
		strcpy(g_cur_env, cur_env);
}

unsigned char get_string_param(char* group, char* item_key, 
						 char* item_value, unsigned long len)
{
	char config_file_name[512];
	
	if(!item_value)
		return FALSE;
	
	get_config_file_name(config_file_name);
	item_value[0] = 0;
	
	get_string_from_profile(group, item_key,
		"", item_value, len, config_file_name);
	
	int str_len = strlen(item_value);
	if(str_len > 0)
	{
		// for old INI format
		if(item_value[str_len - 1] == ';')
			item_value[str_len - 1] = 0;
	}
	
	return str_len > 0;
}

int get_int_param(char* group, char* item_key)
{
	char str_value[256];
	
	if(get_string_param(group, item_key, str_value, 256))
	{
		int i;
		sscanf(str_value, "%d", &i);
		
		return i;
	}
	return 0;
}

unsigned short get_uint16_param(char* group, char* item_key)
{
	char str_value[256];
	
	if(get_string_param(group, item_key, str_value, 256))
	{
		int i;
		sscanf(str_value, "%d", &i);
		
		return (unsigned short)i;
	}
	
	return 0;
}

DWORD get_uint32_param(char* group, char* item_key)
{
	char str_value[256];
	
	if(get_string_param(group, item_key, str_value, 256))
	{
		DWORD i;
		sscanf(str_value, "%u", &i);
		
		return i;
	}
	
	return 0;
}

unsigned char get_bool_param(char* group, char* item_key, 
					   unsigned char default_value)
{
	char str_value[256];
	
	if(get_string_param(group, item_key, str_value, 256))
#ifndef RT_WIN32
		return strcasecmp(str_value, "TRUE") == 0; 
#else //RT_WIN32
		return stricmp(str_value, "TRUE") == 0; 
#endif //RT_WIN32
	
	return default_value;
}

/*
* For compatibility with Solaris, provide get_exec_name(), which attempts to
* return the name of the current executable by looking it up in /proc.
*/
const char* get_exec_name(void)
{
#define CMDBUFLEN 1024 /* PATH_MAX */
	static char cmd_name_buf[CMDBUFLEN + 1];
	static char *cmd_name = NULL;
	
#ifndef RT_WIN32
	char pidfile[64];
	if (!cmd_name)
	{
		int bytes;
		int fd;
		
		sprintf(pidfile, "/proc/%d/cmdline", getpid());
		
		fd = open(pidfile, O_RDONLY, 0);
		bytes = read(fd, cmd_name_buf, 256);
		close(fd);
		
		cmd_name_buf[CMDBUFLEN] = '\0';
		cmd_name = cmd_name_buf;
	}

#else
	if (!cmd_name) {
		::GetModuleFileNameA(NULL, cmd_name_buf, sizeof(cmd_name_buf));
		cmd_name = cmd_name_buf;
	}

#endif // !RT_WIN32
	return(cmd_name);
}

const char* get_process_name()
{
	const char* pExecName = get_exec_name();
	
	if(pExecName)
	{
		const char* pch = pExecName + strlen(pExecName) - 1;
		while(pch > pExecName && *pch != '/')
			pch--;
		
		if(*pch == '/')
			pch++;
		
		return pch;
	}
	else
	{
		return "defproc";
	}
}

